﻿using System.Threading.Tasks;

namespace Sidvall.LogManager.Workflow
{
    public class LogCleanupWorkItem : WorkItemBase
    {
        #region Public Members

        #region ExecuteAsync

        public async Task<ResultContext> ExecuteAsync(LogCleanupContext context)
        {
            this.Context = Sidvall.Serialization.SerializerManager.Current.SerializeObject(context);
            return await ExecuteAsync().ConfigureAwait(false);
        }
        public override async Task<ResultContext> ExecuteAsync()
        {
            DeserializeContext();
            try
            {
                // Delete expired tokens from sources
                foreach (var logTarget in this.ContextItem.LogTargets)
                {
                    var expiry = GetExpiry(logTarget.DayCount);
                    var logResult = await DeleteExpiredLogScopeItemsAsync(logTarget.ConnectionString, logTarget.LogScopeId, expiry).ConfigureAwait(false);
                    this.ExecutionContextItem.LogResults.Add(logResult);
                }

                SerializeContext();
            }
            finally
            {
            }
            return new ResultContext(true, this.ExecutionContextItem.ToString());
        }

        #endregion

        #endregion
        #region Private Members

        private LogCleanupContext ContextItem { get; set; }
        private LogCleanupExecutionContext ExecutionContextItem { get; set; }

        #region DeleteExpiredLogScopeItemsAsync

        private async Task<LogResult> DeleteExpiredLogScopeItemsAsync(string connectionString, long? logScopeId, System.DateTime? expiry)
        {
            var logResult = new LogResult()
            {
                ConnectionString = connectionString,
            };
            if (!string.IsNullOrWhiteSpace(connectionString))
            {
                Sidvall.LogManager.SystemContext.Current.InitializeServerDataLayer(connectionString);
                logResult.DeletedCount = await Sidvall.LogManager.SystemContext.Current.DataPortal.LogScopeItemManager.DeleteLogScopeItemsAsync(null,
                    logScopeId, null, null, null, expiry).ConfigureAwait(false);
                logResult.Count = await Sidvall.LogManager.SystemContext.Current.DataPortal.LogScopeItemManager.GetItemCountAsync().ConfigureAwait(false);
            }
            else
            {
                logResult.DeletedCount = 0;
                logResult.Count = null;
            }
            return logResult;
        }

        #endregion
        #region DeserializeContext

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
        private void DeserializeContext()
        {
            this.ContextItem = Sidvall.Serialization.SerializerManager.Current.Deserialize<LogCleanupContext>(this.Context);
            this.ExecutionContextItem = null;
            try
            {
                if (!string.IsNullOrWhiteSpace(this.ExecutionContext))
                    this.ExecutionContextItem = Sidvall.Serialization.SerializerManager.Current.Deserialize<LogCleanupExecutionContext>(this.ExecutionContext);
            }
            catch
            {
                this.ExecutionContextItem = null;
            }
            if (this.ExecutionContextItem == null)
                this.ExecutionContextItem = new LogCleanupExecutionContext();
            this.ExecutionContextItem.LogResults = new LogResultCollection();
        }

        #endregion
        #region GetExpiry

        private static System.DateTime? GetExpiry(int? dayCount)
        {
            if (dayCount == null)
                return null;
            if (dayCount <= 0)
                dayCount = 31;
            return System.DateTime.UtcNow.Subtract(new System.TimeSpan(dayCount.Value, 0, 0, 0));

        }

        #endregion
        #region SerializeContext

        private void SerializeContext()
        {
            this.ExecutionContext = Sidvall.Serialization.SerializerManager.Current.SerializeObject(this.ExecutionContextItem);
        }

        #endregion

        #endregion
    }
}
